//
//  SQWebSocket.m
//  AI
//
//  Created by 甘世清 on 2024/4/28.
//

#import "SQWebSocket.h"
#import <SocketRocket/SocketRocket.h>

 
@interface SQWebSocket ()<SRWebSocketDelegate>
@property (nonatomic,strong)SRWebSocket *webSocket;

@property (nonatomic,assign)SQSocketStatus SQ_socketStatus;

@property (nonatomic,weak)NSTimer *timer;

@property (nonatomic,weak)NSTimer *timer60;//每60秒发送心跳

@property (nonatomic,copy)NSString *urlString;

@end

@implementation SQWebSocket{
    NSInteger _reconnectCounter;
}

+ (instancetype)shareManager{
    static SQWebSocket *instance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[self alloc] init];
        instance.overtime = 1;
        instance.reconnectCount = 15;
    });
    return instance;
}

- (void)SQ_open:(NSString *)urlStr connect:(SQSocketDidConnectBlock)connect receive:(SQSocketDidReceiveBlock)receive failure:(SQSocketDidFailBlock)failure{
    [SQWebSocket shareManager].connect = connect;
    [SQWebSocket shareManager].receive = receive;
    [SQWebSocket shareManager].failure = failure;
    [self SQ_open:urlStr];
}

- (void)SQ_close:(SQSocketDidCloseBlock)close{
    [SQWebSocket shareManager].close = close;
    [self SQ_close];
}

// Send a UTF8 String or Data.
- (void)SQ_send:(id)data isSend:(nonnull SQSocketDidSendBlock)sendBlock{
    switch ([SQWebSocket shareManager].SQ_socketStatus) {
        case SQSocketStatusConnected:
        case SQSocketStatusReceived:{
            NSLog(@"发送中。。。");
       BOOL isSend = [self.webSocket sendString:data error:nil];
            if (sendBlock) {
                sendBlock(isSend);
            }
            break;
        }
        case SQSocketStatusFailed:
            NSLog(@"发送失败");
            if (sendBlock) {
                sendBlock(NO);
            }
            _reconnectCounter = 0;
            [self SQ_reconnect];
            break;
        case SQSocketStatusClosedByServer:
            NSLog(@"已经关闭");
            if (sendBlock) {
                sendBlock(NO);
            }
            _reconnectCounter = 0;
            [self SQ_reconnect];
            break;
        case SQSocketStatusClosedByUser:
            NSLog(@"已经关闭");
            if (sendBlock) {
                sendBlock(NO);
            }
            _reconnectCounter = 0;
            [self SQ_reconnect];
            break;
    }
    
}

#pragma mark -- private method
- (void)SQ_open:(id)params{
//    NSLog(@"params = %@",params);
    NSString *urlStr = nil;
    if ([params isKindOfClass:[NSString class]]) {
        urlStr = (NSString *)params;
    }
    else if([params isKindOfClass:[NSTimer class]]){
        NSTimer *timer = (NSTimer *)params;
        urlStr = [timer userInfo];
    }
    [SQWebSocket shareManager].urlString = urlStr;
    [self.webSocket close];
    self.webSocket.delegate = nil;
    
    self.webSocket = [[SRWebSocket alloc] initWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:urlStr]]];
    self.webSocket.delegate = self;
    
    [self.webSocket open];
}

- (void)SQ_close{
    [self.timer60 invalidate];
    self.timer60 = nil;
    [self.webSocket close];
    self.webSocket = nil;
    [self.timer invalidate];
    self.timer = nil;

}

- (void)SQ_reconnect{
    // 计数+1
    if (_reconnectCounter < self.reconnectCount - 1) {
        _reconnectCounter ++;
        // 开启定时器
        if (!self.timer) {
            NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:self.overtime target:self selector:@selector(SQ_open:) userInfo:self.urlString repeats:NO];
            [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
            self.timer = timer;
        }  
    }
    else{
        NSLog(@"Websocket Reconnected Outnumber ReconnectCount");
        if (self.timer) {
            [self.timer invalidate];
            self.timer = nil;
        }
      
        return;
    }
    
}

#pragma mark -- SRWebSocketDelegate
- (void)webSocketDidOpen:(SRWebSocket *)webSocket{
//    DTLog(@"链接成功了---- Websocket Connected %@",[NSString SQ_currentTime]);
    [SQWebSocket shareManager].connect ? [SQWebSocket shareManager].connect() : nil;
    [SQWebSocket shareManager].SQ_socketStatus = SQSocketStatusConnected;
    // 开启成功后重置重连计数器
    _reconnectCounter = 0;
    //给服务器发心跳
    if (self.timer60) {
        [self.timer60 invalidate];
        self.timer60 = nil;
    }
    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:@selector(SQ_60Time) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
    self.timer60 = timer;
     
}
-(void)SQ_60Time{
   
    //发消息
    NSMutableDictionary * dic = [[NSMutableDictionary alloc]init];
    [dic setObject:@"pong" forKey:@"content"];
    [dic setObject:@"0" forKey:@"order"];
    [[SQWebSocket shareManager]SQ_send:[dic mj_JSONString] isSend:^(BOOL isSend) {
         
    }];
}

- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error{
    NSLog(@":( Websocket Failed With Error %@", error);
    [SQWebSocket shareManager].SQ_socketStatus = SQSocketStatusFailed;
    [SQWebSocket shareManager].failure ? [SQWebSocket shareManager].failure(error) : nil;
    // 重连
    [self SQ_reconnect];
}

- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message{
//    NSLog(@":( Websocket Receive With message %@", message);
    [SQWebSocket shareManager].SQ_socketStatus = SQSocketStatusReceived;
    [SQWebSocket shareManager].receive ? [SQWebSocket shareManager].receive(message,SQSocketReceiveTypeForMessage) : nil;
}

- (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean{
    NSLog(@"Closed Reason:%@  code = %zd   %@",reason,code,[NSString SQ_currentTime]);
    if (reason) {
        [SQWebSocket shareManager].SQ_socketStatus = SQSocketStatusClosedByServer;
        // 重连
        [self SQ_reconnect];
    }
    else{
        [SQWebSocket shareManager].SQ_socketStatus = SQSocketStatusClosedByUser;
    }
    [SQWebSocket shareManager].close ? [SQWebSocket shareManager].close(code,reason,wasClean) : nil;
    self.webSocket = nil;
}

- (void)webSocket:(SRWebSocket *)webSocket didReceivePong:(NSData *)pongPayload{
    [SQWebSocket shareManager].receive ? [SQWebSocket shareManager].receive(pongPayload,SQSocketReceiveTypeForPong) : nil;
}

- (void)dealloc{
    // Close WebSocket
    
    [self SQ_close];
}
@end
